package com.mask.encryption.web;

import com.mask.encryption.config.MaskEncryptionWebProperties;
import com.mask.encryption.service.MaskEncryptionService;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;

@ControllerAdvice
public class MaskEncryptResponseBodyAdvice implements ResponseBodyAdvice<Object> {

    private final MaskEncryptionService encryptionService;
    private final MaskEncryptionWebProperties webProps;
    private final HttpServletRequest request;
    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    public MaskEncryptResponseBodyAdvice(MaskEncryptionService encryptionService,
                                         MaskEncryptionWebProperties webProps,
                                         HttpServletRequest request) {
        this.encryptionService = encryptionService;
        this.webProps = webProps;
        this.request = request;
    }

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        if (!webProps.isEnabled() || !webProps.isEncryptResponse()) {
            return false;
        }
        String uri = request.getRequestURI();
        for (String pattern : webProps.getIgnorePaths()) {
            if (pathMatcher.match(pattern, uri)) {
                return false;
            }
        }
        if (webProps.isRequireHeader()) {
            String hv = request.getHeader(webProps.getHeaderToggle());
            if (hv == null || hv.isEmpty()) {
                return false;
            }
        }
        return MappingJackson2HttpMessageConverter.class.isAssignableFrom(converterType);
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  ServerHttpRequest request, ServerHttpResponse response) {
        if (body == null) {
            return null;
        }
        // 将对象序列化为 JSON 字符串再加密（交由 MappingJackson2Converter 完成序列化不容易在此拿到原 JSON）
        // 兼容处理：这里直接返回 Base64 字符串，前端拿到后解密再 JSON.parse
        String json = com.fasterxml.jackson.databind.json.JsonMapper.builder().build().valueToTree(body).toString();
        return encryptionService.encryptToBase64(json);
    }
}


